﻿using Quartz;
using System.Reflection;
using System.Reflection.Emit;
using TasksManager.Jobs.Test;

namespace TasksManager.Jobs
{
    public class SchedulerServer : ISchedulerServer
    {
        private IScheduler scheduler;
        private ISchedulerFactory schedulerFactory;
        private IConfiguration configuration;

        public SchedulerServer(ISchedulerFactory _schedulerFactory, IConfiguration _configuration)
        {
            if (_schedulerFactory == null)
                throw new Exception($"{nameof(ISchedulerFactory)}");
            schedulerFactory = _schedulerFactory;
            configuration = _configuration;
        }

        protected virtual Task<IScheduler> GetScheduler()
        {
            return schedulerFactory.GetScheduler();
        }

        public async Task InitAsync()
        {
            try
            {
                scheduler = await GetScheduler();
                await RegirstJobAsync();
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public void Start()
        {
            try
            {
                scheduler.Start();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void Pause()
        {
            scheduler.PauseAll();
        }

        public void Resume()
        {
            scheduler.ResumeAll();
        }


        public void Stop()
        {
            try
            {
                scheduler.Shutdown(true);
            }
            catch (Exception ex)
            {
                //logger.Error($"Scheduler stop failed: {ex.Message}", ex);
                throw ex;
            }
        }
        private async Task RegirstJobAsync()
        {
            Assembly assembly = Assembly.GetAssembly(typeof(IBaseJob));
            Type[] types = assembly.GetTypes();
            foreach (Type item in types)
            {
                JobAttribute jobAttribute = item.GetCustomAttribute<JobAttribute>();
                if (item.IsClass && jobAttribute != null)
                {
                    IJobDetail job = JobBuilder.Create(item)
                        // 加入数据
                        //.SetJobData(new JobDataMap() {
                        //  new KeyValuePair<string, object>{ }
                        //})
                      .WithIdentity(jobAttribute.JobName,jobAttribute.GroupName)
                      .Build();

                    var trigger = TriggerBuilder.Create()
                        .WithIdentity(jobAttribute.TriggerName,jobAttribute.GroupName);

                    string cron = "";
                    if (string.IsNullOrWhiteSpace(jobAttribute.Cron))
                    {
                        string sectionStr = configuration.GetSection($"Quartz:{jobAttribute.JobName}").Value ?? "";
                        if (string.IsNullOrWhiteSpace(sectionStr))
                        {
                            Console.WriteLine(new Exception("配置异常，请在配置文件中或手动配置任务时间"));
                            break;
                        }
                        else
                            cron = sectionStr.ToString();
                    }
                    else
                        cron = jobAttribute.Cron;

                    if (jobAttribute.IsStartNow)
                        trigger.StartNow();

                    //trigger.ForJob(jobAttribute.JobName, jobAttribute.GroupName);
                    trigger.WithCronSchedule(cron);

                    await scheduler.ScheduleJob(job, trigger.Build());
                }

            }
        }
    }

    public interface ISchedulerServer
    {
        /// <summary>
        /// 初始化
        /// </summary>
        /// <returns></returns>
        Task InitAsync();

        /// <summary>
        /// 开始
        /// </summary>
        /// <returns></returns>
        void Start();

        /// <summary>
        /// 停止
        /// </summary>
        void Stop();

        /// <summary>
        /// 暂停
        /// </summary>
        void Pause();

        /// <summary>
        /// 恢复
        /// </summary>
        void Resume();
    }
}
